package com.lancoo.ccas53.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.mapper.PlanTeachingCourseMapper;
import com.lancoo.ccas53.mapper.PlanTeachingMapper;
import com.lancoo.ccas53.mapper.PlanTeachingStudentMapper;
import com.lancoo.ccas53.pojo.common.PageInfo;
import com.lancoo.ccas53.pojo.dto.CollegePlanDto;
import com.lancoo.ccas53.pojo.dto.CourseAndApplyDto;
import com.lancoo.ccas53.pojo.dto.PlanTeachingDto;
import com.lancoo.ccas53.pojo.response.Scheme;
import com.lancoo.ccas53.pojo.vo.*;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.BatchInsert;
import com.lancoo.ccas53.util.PagingUtil;
import com.lancoo.ccas53.util.WeekUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 * 教务获取教学计划,相当于专业版本 服务实现类
 * </p>
 *
 * @author quin.song
 * @since 2024-05-20
 */
@Service
@Slf4j
public class PlanTeachingServiceImpl extends ServiceImpl<PlanTeachingMapper, PlanTeaching> implements PlanTeachingService {

    @Resource
    private PlanTeachingCourseService planTeachingCourseService;
    @Resource
    private PlanTeachingStudentService planTeachingStudentService;
    @Resource
    private CourseService courseService;
    @Resource
    @Lazy
    private YunBasicService yunBasicService;
    @Resource
    private PlanTeachingMapper planTeachingMapper;
    @Resource
    private PlanTeachingCourseMapper planTeachingCourseMapper;
    @Resource
    private PlanTeachingStudentMapper planTeachingStudentMapper;
    @Resource
    private CourseApplyService courseApplyService;

    @Autowired
    private TaskInfoService taskInfoService;

    @Autowired
    private RuleWeekDayService ruleWeekDayService;

    @Autowired
    private TypeService typeService;
    @Resource
    @Lazy
    private YunBasicServiceImpl yunBasicServiceImpl;
    @Resource
    private CollegeService collegeService;
    @Resource
    private CourseWeekService courseWeekService;
    @Resource
    private MajorGradeService majorGradeService;

    @Override
    public void syncEducational(Integer taskId, String schoolId, String term) {
        List<Scheme> schemeList = yunBasicService.getBasePlanTeaching(taskId, schoolId);

        //事务会导致缓存空列表
        List<PlanTeaching> planTeachings = new ArrayList<>();
        List<PlanTeachingCourse> planTeachingCourses = new ArrayList<>();
        List<PlanTeachingStudent> planTeachingStudents = new ArrayList<>();
        Set<Course> courses = new HashSet<>();
        schemeList = schemeList.stream().filter(a -> StringUtils.isNotBlank(a.getGradeName())
                && StringUtils.isNotBlank(a.getCollegeID())
                && StringUtils.isNotBlank(a.getMajorID())).collect(Collectors.toList());
        for (Scheme scheme : schemeList) {
            //如果该教学计划存在课程，则置为true，同步该条教学计划
            boolean isExist = false;
            //根据学期判断是否需要上该课
            for (Scheme.CourseListDTO plan : scheme.getCourseList()) {
                //不同步辅修计划  因为双学位包括辅修计划
//                if (scheme.getSchemeType() == 2) {
//                    continue;
//                }
                //获取当前学期是该培养计划对应年级的第几个学期，比如2020级的培养方案是2022-202301学期的第五个学期
                int openingTerm = WeekUtil.getOpeningTerm(term, scheme.getGradeName());
                //判断该课程的开课学期中是否包含当前学期===当前学期是否开这门课程
                if (!plan.getTerms().contains(String.valueOf(openingTerm))) {
                    continue;
                }
                if (CollUtil.isEmpty(scheme.getStudentList())) {
                    //没有应用人数的培养计划不同步
                    continue;
                }
                isExist = true;
                int flag = Integer.parseInt(plan.getPlanType());
                Course course = new Course()
                        .setTaskId(taskId)
                        .setBaseCourseId(plan.getPlanID())
                        .setCourseName(plan.getCourseName())
                        .setCourseTypeId(plan.getPlanKindID())
                        .setCourseType(plan.getPlanKindName())
                        .setCourseNature(plan.getCourseProp())
                        .setMajorProp(plan.getMajorProp())
                        .setCourseCode(plan.getCourseCode())
                        .setBaseCollegeId(plan.getCollegeID())
                        .setCollegeName(plan.getCollegeName())
                        .setSubjectId(plan.getSubjectID())
                        .setSubjectName(plan.getSubjectName())
                        .setCredit(plan.getCredit())
                        .setLectureHour(plan.getLectureHours())
                        .setExperimentalHour(plan.getExperimentHours())
                        .setComputerHour(plan.getOperationHours())
                        .setOtherHour(plan.getOtherHours())
                        .setWeekNum(plan.getTotalHour())
                        .setFlag(flag)
                        .setIsEnable(0);
                courses.add(course);

                //添加课程环节中间表
                planTeachingCourses.add(new PlanTeachingCourse()
                        .setTaskId(taskId)
                        .setBaseTeachingPlanId(scheme.getSchemeID())
                        .setBaseCourseId(plan.getPlanID())
                        .setFlag(flag));
            }
            if (isExist) {
                //教学计划
                planTeachings.add(scheme.toPlanTeaching(taskId));
                //教学计划学生
                planTeachingStudents.addAll(scheme.toPlanTeachingStudent(taskId));
            }
        }
        //插入、更新或删除教学计划
        this.syncPlanTeaching(taskId, planTeachings);
        this.syncPlanSegCou(taskId, planTeachingCourses);
        this.syncPlanStudent(taskId, planTeachingStudents);
        courseService.syncPlanCourse(taskId, courses);
    }

    @Override
    public PlanTeachingDto getTeacherPlan(PlanTeachingVo param, Integer taskId) {
        PlanTeachingDto result = new PlanTeachingDto();
        result.setCurrentPage(param.getCurrentPage());
        result.setPageSize(param.getPageSize());

        List<MajorGrade> majorGradeList = majorGradeService.lambdaQuery().eq(MajorGrade::getTaskId, taskId).list();
        List<String> collegeIds = majorGradeList.stream().map(MajorGrade::getBaseCollegeId).collect(Collectors.toList());
        List<String> gradeIds = majorGradeList.stream().map(MajorGrade::getGradeId).collect(Collectors.toList());
        List<String> majorIds = majorGradeList.stream().map(MajorGrade::getBaseMajorId).collect(Collectors.toList());

        QueryWrapper<PlanTeaching> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id", taskId);
        queryWrapper.eq(StringUtils.isNotBlank(param.getGradeId()), "grade_id", param.getGradeId());
        queryWrapper.eq(param.getStudyNature() != null, "study_nature", param.getStudyNature());
        queryWrapper.eq(param.getIsEnable() != null, "is_enable", param.getIsEnable());
        queryWrapper.eq(StringUtils.isNotBlank(param.getBaseCollegeId()), "base_college_id", param.getBaseCollegeId());
        queryWrapper.eq(StringUtils.isNotBlank(param.getBaseMajorId()), "base_major_id", param.getBaseMajorId());
        //过滤教学计划，以基础平台的年级专业为主
        queryWrapper.in("base_college_id",collegeIds);
        queryWrapper.in("grade_id",gradeIds);
        queryWrapper.in("base_major_id",majorIds);
        queryWrapper.orderByAsc("teaching_plan_id");
        Page page = new Page(param.getCurrentPage(), param.getPageSize());
        List<PlanTeaching> list = page(page, queryWrapper).getRecords();

        QueryWrapper<PlanTeachingCourse> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("task_id", taskId);
        List<PlanTeachingCourse> planTeachingCourses = planTeachingCourseService.list(queryWrapper1);

        List<PlanTeachingVo> planTeachingVos = new ArrayList<>();
        for (PlanTeaching item : list
        ) {
            PlanTeachingVo view = new PlanTeachingVo();
            BeanUtils.copyProperties(item, view);
            view.setSegmentNum((int) planTeachingCourses.stream().filter(a -> a.getBaseTeachingPlanId().equals(item.getBaseTeachingPlanId()) && a.getFlag().equals(2)).count());
            view.setCourseNum((int) planTeachingCourses.stream().filter(a -> a.getBaseTeachingPlanId().equals(item.getBaseTeachingPlanId()) && a.getFlag().equals(1)).count());
            planTeachingVos.add(view);
        }

        int enableNum = 0, unableNum = 0;
        for (PlanTeachingVo planTeachingVo : planTeachingVos) {
            switch (planTeachingVo.getIsEnable()) {
                case 0:
                    unableNum += 1;
                    break;
                case 1:
                    enableNum += 1;
                    break;
                default:
                    break;
            }
        }
        result.setEnableNum(enableNum);
        result.setUnableNum(unableNum);
        result.setPlanTeachingList(planTeachingVos);
        result.setTotal((int) page.getTotal());
        result.setPages((int) page.getPages());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setTeacherPlan(Integer isEnable, Integer taskId, List<Long> idList) {
        List<PlanTeaching> list = planTeachingMapper.getPlanTeaching(taskId);
        for (Long id : idList
        ) {
            PlanTeaching model = list.stream().filter(a -> a.getTeachingPlanId().equals(id)).findFirst().get();
            model.setIsEnable(isEnable);
            boolean flag = updateById(model);
            if (!flag) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }
        return true;
    }

    @Override
    public Boolean clearTeacherPlan(Integer taskId) {
        List<Long> planIds = this.lambdaQuery().eq(PlanTeaching::getTaskId, taskId).list()
                .stream().map(PlanTeaching::getTeachingPlanId).collect(Collectors.toList());
        return this.lambdaUpdate().in(PlanTeaching::getTeachingPlanId, planIds)
                .set(PlanTeaching::getIsEnable, 1).update();
    }

    @Override
    public List<CourseVo> getCourseByTeachingPlanId(String baseTeachingPlanId, Integer flag, Integer taskId) {
        List<CourseVo> result = new ArrayList<>();
        List<PlanTeachingCourse> list = planTeachingCourseService.lambdaQuery().eq(PlanTeachingCourse::getBaseTeachingPlanId, baseTeachingPlanId)
                .eq(PlanTeachingCourse::getTaskId, taskId).eq(PlanTeachingCourse::getFlag, flag).list();
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getFlag, flag).eq(Course::getTaskId, taskId).list();
        for (PlanTeachingCourse item : list
        ) {
            List<Course> courses = courseList.stream().filter(a -> a.getBaseCourseId().equals(item.getBaseCourseId())).collect(Collectors.toList());
            for (Course course : courses) {
                CourseVo view = new CourseVo();
                BeanUtils.copyProperties(course, view);
                WeekDateVo data = taskInfoService.countWeek(taskId);
                view.setWeekCount(data.getWeekCount());
                result.add(view);
            }
        }
        return result;
    }

    @Override
    public List<PlanTeaching> getTeachingPlanByCourse(String baseCourseId, Integer taskId) {
        List<PlanTeaching> result = new ArrayList<>();

        QueryWrapper<PlanTeachingCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_course_id", baseCourseId);
        queryWrapper.eq("task_id", taskId);
        List<PlanTeachingCourse> list = planTeachingCourseService.list(queryWrapper);

        for (PlanTeachingCourse item : list) {
            QueryWrapper<PlanTeaching> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("base_teaching_plan_id", item.getBaseTeachingPlanId());
            queryWrapper1.eq("task_id", item.getTaskId());
            queryWrapper1.eq("is_enable", 1);
            List<PlanTeaching> planTeachingList = list(queryWrapper1);
            result.addAll(planTeachingList);
        }
        return result;
    }

    @Override
    public List<CourseType> getCourseType(String flag, Integer taskId) {
        List<CourseType> result = new ArrayList<>();
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getTaskId, taskId).eq(ObjUtil.isNotEmpty(flag), Course::getFlag, flag).list();
        List<String> typeIds = courseList.stream().map(Course::getCourseTypeId).distinct().collect(Collectors.toList());
        for (String typeId : typeIds) {
            CourseType view = new CourseType();
            view.setCourseType(courseList.stream().filter(a -> a.getCourseTypeId().equals(typeId)).findFirst().get().getCourseType());
            view.setCourseTypeId(typeId);
            result.add(view);
        }
        return result;
    }

    @Override
    public CourseAndApplyDto getCourseAndApply(CourseVo param, Integer taskId) {
        CourseAndApplyDto result = new CourseAndApplyDto();
        WeekDateVo data = taskInfoService.countWeek(taskId);
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getTaskId, taskId).list();
        List<Long> courseIds = courseList.stream().map(Course::getCourseId).collect(Collectors.toList());
        List<CourseApply> courseApplyList = courseApplyService.lambdaQuery().eq(CourseApply::getTaskId, taskId).list();
        List<PlanTeaching> allPlanTeaching = this.lambdaQuery().eq(PlanTeaching::getTaskId, taskId).list();
        List<CourseWeek> courseWeekList = courseWeekService.lambdaQuery().in(CourseWeek::getCourseId, courseIds).list();
        List<Type> types = typeService.lambdaQuery().eq(Type::getTaskId, taskId).list();
        Page<MajorGrade> page = new Page<>(param.getCurrentPage(), 10000);
        PageInfo<MajorGrade> allMajorGrade = ruleWeekDayService.getMajorGradeActiveTeachList(page, taskId, null, null, null, null);

        //因为本系统可以选择去无条件同步基础平台课程库中所有课程，所以不能直接拿所有的课程遍历
        //同步培养方案时，该培养方案下的课程，只有本学期开的课程会存入中间表PlanTeachingCourse，从中间表获取到本学期开课的课程
        List<PlanTeachingCourse> planTeachingCourses = planTeachingCourseService.lambdaQuery().eq(PlanTeachingCourse::getTaskId, taskId).list();
        List<String> baseCourseIds = planTeachingCourses.stream().map(PlanTeachingCourse::getBaseCourseId).collect(Collectors.toList());
        courseList = courseList.stream().filter(a -> baseCourseIds.contains(a.getBaseCourseId())).collect(Collectors.toList());

        List<CourseVo> courseVoList = new ArrayList<>();
        for (Course item : courseList) {//
            CourseVo view = new CourseVo();
            //培养方案
            List<PlanTeaching> list1 = getTeachingPlanByCourse(item.getBaseCourseId(), taskId);
            view.setPlanTeachingCount(list1.size());
            int studentCount = list1.stream().mapToInt(PlanTeaching::getStudentCount).sum();
            //培养方案人数
            view.setPlanTeachingStudentCount(studentCount);

            Optional<CourseApply> courseApply = courseApplyList.stream().filter(a -> a.getCourseId().equals(item.getCourseId())).findFirst();
            BeanUtils.copyProperties(item, view);
            if (courseApply.isPresent()) {
                if (courseApply.get().getApplyStatus() == 3 || courseApply.get().getApplyStatus() == 1) {
                    BeanUtils.copyProperties(courseApply.get(), view);
                }
                view.setApplyId(courseApply.get().getApplyId());
                view.setApplyStatus(courseApply.get().getApplyStatus());
                view.setOperationType(courseApply.get().getOperationType());
                view.setDescription(courseApply.get().getDescription());
                view.setReviewComment(courseApply.get().getReviewComment());
                view.setCreatedUserId(courseApply.get().getCreatedUserId());
                view.setCreatedUserName(courseApply.get().getCreatedUserName());
                view.setWeekNum(courseApply.get().getWeekNum());
            } else {
                view.setApplyStatus(1);
                view.setOperationType(1);
            }
            if (ObjUtil.isNull(view.getApplyStatus())) {
                view.setApplyStatus(1);
            }
            Optional<PlanTeachingCourse> temp = planTeachingCourses.stream().filter(a -> a.getBaseCourseId().equals(item.getBaseCourseId())).findFirst();
            if (temp.isPresent()) {
                Optional<PlanTeaching> planTeaching = allPlanTeaching.stream().filter(a -> a.getBaseTeachingPlanId().equals(temp.get().getBaseTeachingPlanId())).findFirst();
                if (planTeaching.isPresent()) {
                    view.setMajorId(planTeaching.get().getBaseMajorId());
                    view.setMajorName(planTeaching.get().getMajorName());
                    view.setGradeName(planTeaching.get().getGradeName());
                    view.setGradeId(planTeaching.get().getGradeId());
                    int sum = 0;
                    List<MajorGrade> majorGradeList = allMajorGrade.getList().stream()
                            .filter(a -> a.getBaseCollegeId().equals(item.getBaseCollegeId()))
                            .filter(a -> a.getGradeId().equals(planTeaching.get().getGradeId()))
                            .filter(a -> a.getBaseMajorId().equals(planTeaching.get().getBaseMajorId()))
                            .collect(Collectors.toList());
                    for (MajorGrade grade : majorGradeList
                    ) {
                        List<ActiveTeach> list = grade.getActiveTeachList();
                        if (list != null) {
                            for (ActiveTeach activeTeach : list
                            ) {
                                Optional<Type> type = types.stream().filter(a -> a.getTypeId().equals(activeTeach.getTypeId())).findFirst();
                                if (type.isPresent()) {
                                    if (type.get().getFlag() == 1) {
                                        sum += 1;
                                    }
                                }
                            }
                        }
                    }
                    view.setLackWeekCount(sum);
                }
            }
            view.setWeekCount(data.getWeekCount());
            view.setTeachWeekCount(view.getWeekCount() - view.getLackWeekCount());

            //填充课程参数
            List<CourseWeek> weeks = courseWeekList.stream().filter(a -> a.getCourseId().equals(item.getCourseId())).collect(Collectors.toList());
            view.setCourseWeeks(weeks);
            courseVoList.add(view);
        }
        //筛选
        courseVoList = courseVoList.stream().filter(a -> StringUtils.isBlank(param.getMajorId()) || a.getMajorId().equals(param.getMajorId()))
                .filter(a -> StringUtils.isBlank(param.getGradeId()) || a.getGradeId().equals(param.getGradeId()))
                .filter(a -> StringUtils.isBlank(param.getKeyword()) || a.getCourseName().contains(param.getKeyword()))
                .filter(a -> ObjUtil.isEmpty(param.getFlag()) || a.getFlag().equals(param.getFlag()))
                .filter(a -> ObjUtil.isEmpty(param.getCourseNature()) || a.getCourseNature().equals(param.getCourseNature()))
                .filter(a -> StringUtils.isBlank(param.getCourseTypeId()) || a.getCourseTypeId().equals(param.getCourseTypeId()))
                .filter(a -> StringUtils.isBlank(param.getBaseCollegeId()) || a.getBaseCollegeId().equals(param.getBaseCollegeId()))
                .filter(a -> ObjUtil.isEmpty(param.getOperationType()) || a.getOperationType().equals(param.getOperationType()))
                .filter(a -> ObjUtil.isEmpty(param.getApplyStatus()) || a.getApplyStatus().equals(param.getApplyStatus()))
                .collect(Collectors.toList());

        int count1 = 0;
        int count2 = 0;
        if (ObjUtil.isNotEmpty(param.getApplyStatus())) {
            if (param.getApplyStatus() == 1) {
                //未申请
                count1 = Math.toIntExact(courseVoList.stream().filter(a -> a.getApplyStatus().equals(param.getApplyStatus())).count());
            } else if (param.getApplyStatus() == 2 || param.getApplyStatus() == 3 || param.getApplyStatus() == 4) {
                count2 = Math.toIntExact(courseVoList.stream().filter(a -> a.getApplyStatus().equals(param.getApplyStatus())).count());
            }
        } else {
            count1 = Math.toIntExact(courseVoList.stream().filter(a -> a.getApplyStatus() == 0 || a.getApplyStatus() == 1).count());
            count2 = courseVoList.size() - count1;
        }
        result.setRequested(count2);
        result.setNotRequested(count1);
        //分页
        PageInfo<CourseVo> pageInfo = PagingUtil.getPages(param.getCurrentPage(), param.getPageSize(), courseVoList);
        result.setPages(pageInfo.getPages());
        result.setTotal(pageInfo.getTotal());
        result.setCurrentPage(pageInfo.getCurrentPage());
        result.setPageSize(pageInfo.getPageSize());
        result.setCourseVoList(pageInfo.getList());
        return result;
    }

    @Override
    public Object dealCourseApply(CourseApplyVo param, Integer taskId) {
        Map<String, String> map = new HashMap<>();
        QueryWrapper<CourseApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("course_id", param.getCourseId());
        courseApplyService.remove(queryWrapper);

        CourseApply model = new CourseApply();
        BeanUtils.copyProperties(param, model);
        model.setTaskId(taskId);
        model.setCreatedUserId(param.getUserId());
        model.setCreatedUserName(param.getUserName());
        model.setApplyStatus(2);
        model.setOperationType(param.getOperationType());
        courseApplyService.save(model);
        map.put("appid", courseApplyService.getOne(queryWrapper).getApplyId().toString());
        return map;
    }

    @Override
    public List<CourseVo> getAddCourses(String collegeId, String keyword, Optional<Integer> flag, Integer taskId) {
        List<CourseVo> result = new ArrayList<>();
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(collegeId), "base_college_id", collegeId);
        queryWrapper.eq("task_id", taskId);
        queryWrapper.orderByAsc("course_id");
        flag.ifPresent(integer -> queryWrapper.eq("flag", integer));
        List<Course> courseList = courseService.list(queryWrapper);
        if (StringUtils.isNotBlank(keyword)) {
            courseList = courseList.stream().filter(a -> a.getCourseName().contains(keyword)).collect(Collectors.toList());
        }
        for (Course item : courseList
        ) {
            CourseVo view = new CourseVo();
            BeanUtils.copyProperties(item, view);
            result.add(view);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean examineApply(Integer applyId, String reviewComment, Integer examine, String authorization, String userId, String userName, Integer taskId) {
        CourseApply model = courseApplyService.getById(applyId);
        if (model == null) {
            return false;
        }
        model.setReviewComment(reviewComment);
        model.setApplyStatus(examine == 1 ? 3 : 4);
        model.setTaskId(taskId);
        courseApplyService.updateById(model);
        Course course = courseService.getById(model.getCourseId());

        //消息通知
        MsgCoursePlanExamine msg = new MsgCoursePlanExamine();
        msg.setTaskId(taskId);
        msg.setExamine(examine);
        msg.setUserId(userId);
        msg.setUserName(userName);
        msg.setCourseName(course.getCourseName());
        msg.setSendUserId(model.getCreatedUserId());
        msg.setSendUserName(model.getCreatedUserName());
        yunBasicServiceImpl.sendCoursePlanExamineResultMsg(msg);

        if (examine == 1) {
            if (model.getOperationType() == 3) {
                if (course.getFlag() == 2) {
                    //环节不修改course_week表
                    courseService.lambdaUpdate()
                            .eq(Course::getCourseId, course.getCourseId())
                            .eq(Course::getTaskId, taskId)
                            .set(Course::getWeekNum, model.getWeekNum())
                            .update();
                    return true;
                }
                courseWeekService.lambdaUpdate()
                        .eq(CourseWeek::getTaskId, taskId)
                        .eq(CourseWeek::getCourseId, model.getCourseId())
                        .remove();
                if (model.getComputerHour() != null && model.getComputerHour() != 0) {
                    CourseWeek week = new CourseWeek()
                            .setHourType(3)
                            .setHourTypeName("上机")
                            .setCourseId(model.getCourseId())
                            .setTaskId(taskId)
                            .setTotalHour(model.getComputerHour())
                            .setWeekNum(model.getWeekNum());
                    courseWeekService.save(week);
                }
                if (model.getExperimentalHour() != null && model.getExperimentalHour() != 0) {
                    CourseWeek week = new CourseWeek()
                            .setHourType(2)
                            .setHourTypeName("实验")
                            .setCourseId(model.getCourseId())
                            .setTaskId(taskId)
                            .setTotalHour(model.getExperimentalHour())
                            .setWeekNum(model.getWeekNum());
                    courseWeekService.save(week);
                }
                if (model.getLectureHour() != null && model.getLectureHour() != 0) {
                    CourseWeek week = new CourseWeek()
                            .setHourType(1)
                            .setHourTypeName("讲授")
                            .setCourseId(model.getCourseId())
                            .setTaskId(taskId)
                            .setTotalHour(model.getLectureHour())
                            .setWeekNum(model.getWeekNum());
                    courseWeekService.save(week);
                }
                if (model.getOtherHour() != null && model.getOtherHour() != 0) {
                    CourseWeek week = new CourseWeek()
                            .setHourType(4)
                            .setHourTypeName("其他")
                            .setCourseId(model.getCourseId())
                            .setTaskId(taskId)
                            .setTotalHour(model.getOtherHour())
                            .setWeekNum(model.getWeekNum());
                    courseWeekService.save(week);
                }
                courseService.lambdaUpdate()
                        .eq(Course::getCourseId, model.getCourseId())
                        .set(Course::getLectureHour, model.getLectureHour())
                        .set(Course::getComputerHour, model.getComputerHour())
                        .set(Course::getOtherHour, model.getOtherHour())
                        .set(Course::getExperimentalHour, model.getExperimentalHour())
                        .update();
            } else if (model.getOperationType() == 2) {

            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object addPlanCourse(Integer taskId, String baseTeachingPlanId, String baseCourseId, String remark, Integer flag) {
        Map<String, Integer> map = new HashMap<>();
        List<Course> courseList = courseService.lambdaQuery().eq(Course::getBaseCourseId, baseCourseId).eq(Course::getTaskId, taskId).list();
        for (Course course : courseList) {
            CourseApply courseApply = new CourseApply();
            courseApply.setCourseId(course.getCourseId());
            courseApply.setTaskId(taskId);
            courseApply.setApplyStatus(2);
            courseApply.setOperationType(2);
            BeanUtils.copyProperties(course, courseApply);
            courseApply.setDescription(remark);
            courseApplyService.save(courseApply);

            PlanTeachingCourse model = new PlanTeachingCourse();
            model.setBaseTeachingPlanId(baseTeachingPlanId);
            model.setFlag(flag);
            model.setBaseCourseId(baseCourseId);
            model.setTaskId(taskId);
            planTeachingCourseService.save(model);
            map.put("appid", courseApply.getApplyId());
        }
        return map;
    }

    @Override
    public Map<String, Object> publishStatistics(String baseCollegeId, Integer taskId) {
        Map<String, Object> result = new HashMap<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //开课课程
        int updateCourseNum = 0;
        int addCourseNum = 0;
        int removeCourseNum = 0;
        List<Course> allCourseList = courseService.lambdaQuery()
                .eq(StringUtils.isNotBlank(baseCollegeId), Course::getBaseCollegeId, baseCollegeId)
                .eq(Course::getTaskId, taskId).list();
        //因为本系统可以选择去无条件同步基础平台课程库中所有课程，所以不能直接拿所有的课程遍历
        //同步培养方案时，该培养方案下的课程，只有本学期开的课程会存入中间表PlanTeachingCourse，从中间表获取到本学期课程
        List<String> baseCourseIds = planTeachingCourseService.lambdaQuery().eq(PlanTeachingCourse::getTaskId, taskId).list()
                .stream().map(PlanTeachingCourse::getBaseCourseId).collect(Collectors.toList());
        List<Course> courseList = allCourseList.stream().filter(a -> baseCourseIds.contains(a.getBaseCourseId()) && a.getFlag().equals(1)).collect(Collectors.toList());
        result.put("courseNum", courseList.size());

        List<CourseApply> courseApplyList = courseApplyService.lambdaQuery().eq(CourseApply::getTaskId, taskId).list();
        for (Course item : courseList
        ) {
            Optional<CourseApply> courseApply = courseApplyList.stream().filter(a -> a.getCourseId().equals(item.getCourseId())).findFirst();
            if (courseApply.isPresent()) {
                switch (courseApply.get().getOperationType()) {
                    case 2:
                        addCourseNum += 1;
                        break;
                    case 3:
                        updateCourseNum += 1;
                        break;
                    case 4:
                        removeCourseNum += 1;
                        break;
                }
            }
        }
        result.put("updateCourseNum", updateCourseNum);
        result.put("addCourseNum", addCourseNum);
        result.put("removeCourseNum", removeCourseNum);

        //开课环节
        int updateSegmentNum = 0;
        int addSegmentNum = 0;
        int removeSegmentNum = 0;
        List<Course> segmentList = allCourseList.stream().filter(a -> baseCourseIds.contains(a.getBaseCourseId()) && a.getFlag().equals(2)).collect(Collectors.toList());
        result.put("segmentNum", segmentList.size());

        for (Course item : segmentList
        ) {
            Optional<CourseApply> courseApply = courseApplyList.stream().filter(a -> a.getCourseId().equals(item.getCourseId())).findFirst();
            if (courseApply.isPresent()) {
                switch (courseApply.get().getOperationType()) {
                    case 2:
                        addSegmentNum += 1;
                        break;
                    case 3:
                        updateSegmentNum += 1;
                        break;
                    case 4:
                        removeSegmentNum += 1;
                        break;
                }
            }
        }
        result.put("updateSegmentNum", updateSegmentNum);
        result.put("addSegmentNum", addSegmentNum);
        result.put("removeSegmentNum", removeSegmentNum);

        //专业年级数量 教学计划数量
        QueryWrapper<PlanTeaching> queryWrapper1 = new QueryWrapper();
        queryWrapper1.eq(StringUtils.isNotBlank(baseCollegeId), "base_college_id", baseCollegeId);
        queryWrapper1.eq("task_id", taskId);
        List<PlanTeaching> planTeachingList = list(queryWrapper1);
        List<String> majorList = planTeachingList.stream().map(PlanTeaching::getMajorName).distinct().collect(Collectors.toList());
        result.put("majorGradeNum", majorList.size());
        result.put("planNum", planTeachingList.size());

        if (planTeachingList != null && planTeachingList.size() != 0) {
            List<PlanTeaching> tempPlan = planTeachingList.stream().filter(a -> a.getIsEnable().equals(1)).collect(Collectors.toList());
            float percent = (float) tempPlan.size() / (float) planTeachingList.size();
            percent = (float) Math.round(percent * 1000) / 1000;
            result.put("planPercent", (int) (percent * 100));
        } else {
            result.put("planPercent", 0);
        }

        QueryWrapper<College> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("task_id", taskId);

        List<CollegePlanDto> planDtos = new ArrayList<>();
        List<College> colleges = collegeService.list(queryWrapper2);
        int subCount = 0;
        int notSubCount = 0;
        for (College item : colleges
        ) {
            CollegePlanDto view = new CollegePlanDto();
            view.setCollegeName(item.getCollegeName());
//            view.setFirstTime(dateFormat.format(item.getCoursePlanFirstTime()));
//            view.setLatestTime(dateFormat.format(item.getCoursePlanLatestTime()));
            view.setFirstTime(item.getCoursePlanFirstTime());
            view.setLatestTime(item.getCoursePlanLatestTime());
            view.setPublishManName(item.getCoursePlanUserName());
            if (item.getCoursePlanFirstTime() == null) {
                view.setStatus(0);
                notSubCount += 1;
            } else {
                view.setStatus(1);
                subCount += 1;
            }
            planDtos.add(view);
        }
        result.put("subCount", subCount);
        result.put("notSubCount", notSubCount);
        result.put("collegeCount", colleges.size());
        result.put("collegeDetail", planDtos);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean publishPlan(Integer taskId, String userId, String userName, String baseCollegeId) {
        List<College> toSaveList = new ArrayList<>();
        List<College> collegeList = collegeService.lambdaQuery().eq(College::getTaskId, taskId).eq(StringUtils.isNotBlank(baseCollegeId), College::getBaseCollegeId, baseCollegeId).list();
        for (College college : collegeList) {
            College view = new College();
            BeanUtils.copyProperties(college, view);
            if (view.getCoursePlanFirstTime() == null) {
                view.setCoursePlanFirstTime(LocalDateTime.now());
            }
            view.setCoursePlanLatestTime(LocalDateTime.now());
            view.setCoursePlanUserId(userId);
            try {
                view.setCoursePlanUserName(URLDecoder.decode(userName, "utf-8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            toSaveList.add(view);
        }
        return collegeService.updateBatchById(toSaveList);
    }

    @Override
    public List<CollegePlanDto> getPublishRecord(String baseCollegeId, Integer taskId, Integer type) {
        List<CollegePlanDto> planDtos = new ArrayList<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<College> colleges = collegeService.lambdaQuery()
                .eq(College::getBaseCollegeId, baseCollegeId)
                .eq(College::getTaskId, taskId)
                .list();
        for (College item : colleges
        ) {
            CollegePlanDto view = new CollegePlanDto();
            if (type == 1) {
                //开课计划
                view.setCollegeName(item.getCollegeName());
                view.setFirstTime(item.getCoursePlanFirstTime());
                view.setLatestTime(item.getCoursePlanLatestTime());
                view.setPublishManName(item.getCoursePlanUserName());
            } else if (type == 2) {
                //预选课结果
                view.setCollegeName(item.getCollegeName());
                view.setFirstTime(item.getPreFirstTime());
                view.setLatestTime(item.getPreLatestTime());
                view.setPublishManName(item.getPreUserName());

            } else if (type == 3) {
                //教学任务
                view.setCollegeName(item.getCollegeName());
                view.setFirstTime(item.getTeachingTaskFirstTime());
                view.setLatestTime(item.getTeachingTaskLatestTime());
                view.setPublishManName(item.getTeachingTaskUserName());

            } else if (type == 4) {
                //课表编排
                view.setCollegeName(item.getCollegeName());
                view.setFirstTime(item.getScheduleArrFirstTime());
                view.setLatestTime(item.getScheduleArrLatestTime());
                view.setPublishManName(item.getScheduleArrUserName());

            } else {
                view.setCollegeName(item.getCollegeName());
                view.setFirstTime(item.getSelFirstTime());
                view.setLatestTime(item.getSelLatestTime());
                view.setPublishManName(item.getSelUserName());
                //选课结果
            }
            planDtos.add(view);
        }
        return planDtos;
    }

    public void syncPlanTeaching(Integer taskId, List<PlanTeaching> syncPlanTeaching) {
        List<PlanTeaching> insertList = new ArrayList<>();
        //获取数据库教学计划
        List<PlanTeaching> planTeachingList = this.list(new LambdaQueryWrapper<PlanTeaching>().eq(PlanTeaching::getTaskId, taskId));
        for (PlanTeaching planTeaching : syncPlanTeaching) {
            if (!planTeachingList.contains(planTeaching)) {
                insertList.add(planTeaching);
            }
        }
        planTeachingList.removeAll(syncPlanTeaching);
        List<Long> deleteIds = planTeachingList.stream().map(PlanTeaching::getTeachingPlanId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(deleteIds)) {
            this.removeBatchByIds(deleteIds);
        }
        if (CollUtil.isNotEmpty(insertList)) {
            planTeachingMapper.addBatch(insertList);
        }
    }

    public void syncPlanSegCou(Integer taskId, List<PlanTeachingCourse> syncPlanTeachingCourses) {
        List<PlanTeachingCourse> insertList = new ArrayList<>();
        //获取数据库中间表
        List<PlanTeachingCourse> planTeachingCourseList = planTeachingCourseService.list(new LambdaQueryWrapper<PlanTeachingCourse>().eq(PlanTeachingCourse::getTaskId, taskId));
        for (PlanTeachingCourse planTeachingCourse : syncPlanTeachingCourses) {
            if (!planTeachingCourseList.contains(planTeachingCourse)) {
                insertList.add(planTeachingCourse);
            }
        }
        planTeachingCourseList.removeAll(syncPlanTeachingCourses);
        List<Long> deleteIds = planTeachingCourseList.stream().map(PlanTeachingCourse::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(deleteIds)) {
            planTeachingCourseService.removeBatchByIds(deleteIds);
        }
        if (CollUtil.isNotEmpty(insertList)) {
            planTeachingCourseMapper.addBatch(insertList);
        }
    }

    public void syncPlanStudent(Integer taskId, List<PlanTeachingStudent> syncPlanTeachingStudent) {
        List<PlanTeachingStudent> insertList = new ArrayList<>();
        //获取数据库中间表
        List<PlanTeachingStudent> studentList = planTeachingStudentService.list(new LambdaQueryWrapper<PlanTeachingStudent>().eq(PlanTeachingStudent::getTaskId, taskId));
        for (PlanTeachingStudent planTeachingStudent : syncPlanTeachingStudent) {
            log.info(planTeachingStudent.getBaseStudentId());
            if (!studentList.contains(planTeachingStudent)) {
                insertList.add(planTeachingStudent);
            }
        }
        studentList.removeAll(syncPlanTeachingStudent);
        List<Long> deleteIds = studentList.stream().map(PlanTeachingStudent::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(deleteIds)) {
            planTeachingStudentService.removeBatchByIds(deleteIds);
        }
        if (CollUtil.isNotEmpty(insertList)) {
            //批量插入教学班学生，大数据批量插入
            Consumer<List<PlanTeachingStudent>> studentConsumer = o -> planTeachingStudentMapper.addBatch(o);
            BatchInsert.batchSplitInsert(insertList, studentConsumer);
        }
    }
}
